﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace SynchronizedPlayer {
	abstract class Command {
		public static int Size { get { return 0; } }
		public static readonly char[] FIELD_SEPARATOR = { ' ' };
		public static Dictionary<String, Type> AllCommands { get; private set; }


		public static void BuildDictionary() {
			AllCommands = new Dictionary<string, Type>();
			foreach (var t in Assembly.GetExecutingAssembly().GetTypes()) {
				CommandInfo attr = (CommandInfo)Attribute.GetCustomAttribute(t, typeof(CommandInfo));
				if (attr != null) {
					AllCommands.Add(attr.Name, t);
				}
			}
		}

		public byte[] ToByteArray() {
			string repr = this.ToString();

			byte[] res = new byte[Encoding.ASCII.GetByteCount(repr) + 1];
			res[0] = (byte)(repr.Length);
			Encoding.ASCII.GetBytes(repr).CopyTo(res, 1);
			return res;
		}

		public static Command Parse(byte[] buffer) {
			string repr = System.Text.Encoding.ASCII.GetString(buffer);
			return Parse(repr);
		}

		public static Command Parse(string cmd) {
			string[] repr = cmd.Split(FIELD_SEPARATOR);

			return (Command)Activator.CreateInstance(
					AllCommands.First(kvp => kvp.Key == repr[0])
									.Value,
									new object[] { repr }
					);
		}
	}

	[CommandInfo(Name = "plbegin")]
	class CMDPlaylistBegin : Command {
		public string CurrentTrack { get; private set; }
		public string Position { get; private set; }

		public CMDPlaylistBegin(string[] repr) {
			CurrentTrack = repr[1].ToString();
			Position = repr[2].ToString();
		}

		public CMDPlaylistBegin(string currentTrack, string position) {
			CurrentTrack = currentTrack;
			Position = position;
		}

		public override string ToString() {
			return AllCommands.First(kvp => kvp.Value == this.GetType()).Key
				+ FIELD_SEPARATOR[0] + CurrentTrack + FIELD_SEPARATOR[0] + Position;
		}
	}

	[CommandInfo(Name = "plend")]
	class CMDPlaylistEnd : Command {
		public CMDPlaylistEnd(string[] repr) { }
		public CMDPlaylistEnd() { }

		public override string ToString() {
			return AllCommands.First(kvp => kvp.Value == this.GetType()).Key;
		}
	}

	[CommandInfo(Name = "plitem")]
	class CMDPlaylistItem : Command {
		public string Hash { get; private set; }
		
		public CMDPlaylistItem(string[] repr) {
			Hash = repr[1];
		}
		
		public CMDPlaylistItem(string item) {
			Hash = item;
		}

		public override string ToString() {
			return AllCommands.First(kvp => kvp.Value == this.GetType()).Key + FIELD_SEPARATOR[0] + Hash;
		}
	}
}

